home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
nt
/
lkbackup.zip
/
mttape.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-03
|
98KB
|
3,426 lines
/*
The following is my version of a tape backup program for windows nt
It was written because ntbackup fails on my gigatrend 1200 data drive, but
the driver I wrote for it passes the hardware compat. test fine.
The software allows you to backup/restore savesets to tape (50 savesets max).
It also allows you to list the tape/and or saveset contents and backup/restore
by wildcard ie *dirname* etc. I have implemented compression utilizing a
modified version of gnu zip but on my dat even with a 100K threshold for
zip it takes long and more tape so the compression by default is
disabled unless you specify the -c option. for a list of options run lkbackup -h
The tape drive used by the backup program must have an nt driver and
support the following functions:
1. Writefile/readfile for reading writing to tape
2. it must be device tape0 (ie the first tape device in the system although
this can be changed in the source code)
3. it must support either filemarks or setmarks (default is filemarks
use -s option for setmarks).
4. it must support spacing to end of data and filemark/setmark +/-
spacing
5. it must support scsi data block aka relative blocking/spacing (it
doesn't use absolute or logical blocking).
6. it must support the load/unload/rewind tape apis in win32.
7. You must have your temp variable set since this is where the
zipped/unzipped files are temporarily kept, and there must be enouge space for the
largest of your files (and about 30 of them if using compression).
The program is multi-threaded in that one thread tries to compress ahead of
the thread writting to tape up to 30 files. This improved performance but
uncompressed still works better on my drive. Try it and let me know your
results. Anyway I have left the multi-threading in since with faster machines
or multi-processor machines in the future it will improve perforamce.
The source code is also provided and can be used and modified provided
you send me the modified code with a note about what you are doing.
Also the code cannot be used in a for sale produce without first contacting
me for permission.
Good luck
Larry Kahn 10/27/93
[71534.600] on compuserve
Kahn@drcvax.af.mil on internet
919-630-0412 by phone
919-630-0722 by fax when nt finally gets fax support
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <time.h>
#include <process.h>
#include <string.h>
#include <direct.h>
#include <errno.h>
/* these are the tape functions for my dat drive */
/* lgk use the modified gnu zip compression routines were modifed to provide c level interface
so that we dont need to overhead of a system call */
struct _TAPE_SET_MEDIA_PARAMETERS tparms;
#define max_save_sets 50
#define save_sets_per_block 10
#define blocks_per_header 5
#define bsize1 4096
const int blocksize = bsize1;
DWORD buffersize = bsize1;
const int headersize = 2048;
char saveset_buffer[2049];
BOOLEAN debug = FALSE;
int save_sets_on_tape = 0;
static char backup_version[13] = "LGKBACKUP1.0\0";
unsigned int total_original_size;
unsigned int total_backup_size;
int current_tape_block_number = 0;
BOOLEAN want_compression = TRUE;
volatile int filescompressed = 0;
volatile int filesuncompressed = 0;
DWORD start_time;
typedef struct savesettag {
char filename[300];
unsigned int filesize; /* suports 4 gif */
unsigned int starting_datablock_number;
} SAVESET_HEADER;
SAVESET_HEADER my_saveset_header;
/* 11 per buffer use 4 buffers */
typedef struct tapeheadertag {
char saveset_name[18];
unsigned int original_size;
unsigned int compressed_size;
char date[9];
} TAPE_HEADER;
TAPE_HEADER my_tape_header;
typedef struct rawtag {
char backupversion[13];
TAPE_HEADER header[max_save_sets];
} RAW_TAPE_HEADERT;
/* 15 save sets means we only need the first 512 byte block
since each reacord needs 32 bytes plus the first 12 = 502 total */
RAW_TAPE_HEADERT raw_tape_header;
typedef struct indexrectag {
int original_size;
int compressed_size;
char fname[351];
int start_block;
char date[9];
} INDEX_REC_TYPE;
const int header_size = sizeof(raw_tape_header);
extern int gzip_compress(char *,char *);
extern int gzip_decompress(char *,char *);
FILE *TempIndexFile;
char TempIndexFileName[MAX_PATH];
BOOLEAN tempindexfileopen = FALSE;
HANDLE hTape; /* handle to tape device */
DWORD dwBytesRead, dwBytesWritten, dwPos;
BOOLEAN rdflag, wrflag;
BOOLEAN tape_opened = FALSE;
char todays_date[9];
unsigned int total_bytes_read = 0;
BOOLEAN quiet_mode = FALSE;
BOOLEAN set_mark_positioning = FALSE;
BOOLEAN reading_header = FALSE;
volatile int filesskipped = 0;
CRITICAL_SECTION Protected_Element;
CRITICAL_SECTION Protected_Queue;
BOOLEAN file_mapping = TRUE;
const DWORD compress_threshold = 100000;
/* turn off compression if file > than threshold size */
typedef struct readqueuetag {
char original_filename[400];
char temp_filename[100];
int size;
BOOLEAN compressed;
DWORD attrs;
DWORD lowdate;
DWORD highdate;
} READ_QUEUE_TYPE;
READ_QUEUE_TYPE read_queue[31];
volatile int elements_in_queue = 0;
volatile int current_queue_pop_item = 0;
volatile int current_queue_push_item = 0;
const int queue_size = 30;
volatile BOOLEAN processed_all_files = FALSE;
char Global_SearchString[100];
volatile BOOLEAN global_process_subdirs = FALSE;
BOOLEAN debug_child = FALSE;
volatile BOOLEAN thread_active = FALSE;
HANDLE hThread;
#define severe 1
#define warning 0
/* ------------------------------------------------------------------------------------ */
/* beginning of functions */
/* ------------------------------------------------------------------------------------------- */
int read_elements_in_queue()
{
int rvalue;
EnterCriticalSection(&Protected_Element);
rvalue = elements_in_queue;
LeaveCriticalSection(&Protected_Element);
return(rvalue);
}
/* ------------------------------------------------------------------------------------------- */
void increment_elements_in_queue()
{
EnterCriticalSection(&Protected_Element);
++elements_in_queue;
LeaveCriticalSection(&Protected_Element);
}
/* ------------------------------------------------------------------------------------------- */
void decrement_elements_in_queue()
{
EnterCriticalSection(&Protected_Element);
--elements_in_queue;
LeaveCriticalSection(&Protected_Element);
}
/* ------------------------------------------------------------------------------------------- */
void push_element(element)
READ_QUEUE_TYPE element;
{
EnterCriticalSection(&Protected_Queue);
strcpy(read_queue[current_queue_push_item].original_filename,element.original_filename);
strcpy(read_queue[current_queue_push_item].temp_filename,element.temp_filename);
read_queue[current_queue_push_item].size = element.size;
read_queue[current_queue_push_item].attrs = element.attrs;
read_queue[current_queue_push_item].lowdate = element.lowdate;
read_queue[current_queue_push_item].highdate = element.highdate;
read_queue[current_queue_push_item].compressed = element.compressed;
++current_queue_push_item;
if (current_queue_push_item > 29)
current_queue_push_item = 0;
LeaveCriticalSection(&Protected_Queue);
increment_elements_in_queue();
}
/* ------------------------------------------------------------------------------------------- */
READ_QUEUE_TYPE pop_element()
{
READ_QUEUE_TYPE element;
EnterCriticalSection(&Protected_Queue);
strcpy(element.original_filename,read_queue[current_queue_pop_item].original_filename);
strcpy(element.temp_filename,read_queue[current_queue_pop_item].temp_filename);
element.size = read_queue[current_queue_pop_item].size;
element.attrs = read_queue[current_queue_pop_item].attrs;
element.lowdate = read_queue[current_queue_pop_item].lowdate;
element.highdate = read_queue[current_queue_pop_item].highdate;
element.compressed = read_queue[current_queue_pop_item].compressed;
++current_queue_pop_item;
if (current_queue_pop_item > 29)
current_queue_pop_item = 0;
LeaveCriticalSection(&Protected_Queue);
decrement_elements_in_queue();
return(element);
}
/* ------------------------------------------------------------------------------------------- */
/* recursive wild card search routine */
BOOLEAN wild_match(search_string,target)
char *search_string;
char *target;
{
char *new_target;
int lens = strlen(search_string);
int lent = strlen(target);
BOOLEAN rvalue = FALSE;
/* handle terminating cases first */
if (lens == 1) /* last char of search string */
{
if (strncmp(search_string,"*",1) == 0)
{
/* is a wild card * */
return(TRUE);
}
else if ((strncmp(search_string,"?",1) == 0) && (lent == 1))
{
/* is a wild card ? */
return(TRUE);
}
else /* other char only matches if lent is also 1 and they match */
{
if ((lent == 1) && (strncmp(search_string,target,1) == 0))
return(TRUE);
else return(FALSE);
}
} /* lens = 1 */
else /* lens > 1 */
{
/* now check if chars is ? */
if (strncmp(search_string,"?",1) == 0)
{
/* if ? skip a char in both strings and recurse */
++search_string;
++target;
return(wild_match(search_string,target));
}
/* now check if char is * */
if (strncmp(search_string,"*",1) == 0)
{
/* find next char in search string */
do
{
++search_string;
/* here we also need to skip over ? as long as there is a char left
in the target */
} while (((strncmp(search_string,"*",1) == 0) ||
((strncmp(search_string,"?",1) == 0)) && (lent >= 1)));
/* if it is a ? recurse */
if ((strncmp(search_string,"?",1) == 0) && (lent == 0))
return(FALSE);
else /* other ok character no we need to find this character in the
target and recurse to try and resolve if the recursion fails
we need to try further on in the string do this until we either
suceed or the target string runs out and we fail */
{
rvalue = FALSE;
new_target = search_string;
do
{
new_target = strchr(target,new_target[0]);
if (new_target == NULL)
{
/* couldn't find character so we fail */
return(FALSE);
}
else
{
/* found the char so recurse with it */
rvalue = wild_match(search_string,new_target);
}
/* increment here */
target = new_target;
if (strlen(target) == 1)
return(FALSE);
else ++target;
} while (rvalue == FALSE);
/* if we get out of the inner loop without returning it means
we found a successfull match so we can return it */
return(rvalue);
} /* end of not * or ? */
} /* end of srch string was * */
else
{
/* srch string is another character so find it in target */
/* if next char in target is not the search string then we fail here
otherwise we need to increment both and recurse */
/* we also have a terminating case if if the length of the search string
is greater than one and the length of the remaining target string is only
one since the search string here is not a wildcard */
if (lent <= 1)
return(FALSE);
else if (strncmp(search_string,target,1) != 0)
return(FALSE);
else
{ /* they are equal so recurse through remainder of the string */
++search_string;
++target;
return(wild_match(search_string,target));
}
} /* end search string is regular character case */
} /* end len of srch string > 1 */
} /* end of routine */
/* -------------------------------------------------------------------------------------- */
void store_start_time()
{
start_time = GetTickCount();
}
/* ----------------------------------------------------------------------------------------- */
void close_tape()
{
CloseHandle(hTape);
if (debug)
{
printf("TapeIO:--> Closed Tape Drive\n\n");
fflush(stdout);
}
tape_opened = FALSE;
}
/* ------------------------------------------------------------------------------------------- */
void terminate_program()
{
if (tape_opened)
close_tape();
/* attempt to close the thread handle */
if (thread_active)
CloseHandle(hThread);
exit(1);
}
/* ------------------------------------------------------------------------------------ */
void mt_terminate_program()
{
if (tape_opened)
close_tape();
ExitThread(1);
}
/* ------------------------------------------------------------------------------------ */
/* routine to report an error and terminat if severe */
void report_error(text,rvalue,severity)
char text[20];
DWORD rvalue;
int severity;
{
printf("TapeIO: --> Error %s :",text);
if (rvalue > 0)
printf(" error code returned = %ld ",rvalue);
printf(" Severity = %d \n",severity);
fflush(stdout);
if (severity > 0)
terminate_program();
}
/* --------------------------------------------------------------------------------------- */
/* routine to report an error and terminat if severe */
/* multi threaded version for correct thread cleanup called if thread fails */
void mt_report_error(text,rvalue,severity)
char text[20];
DWORD rvalue;
int severity;
{
printf("TapeIO: --> Error %s :",text);
if (rvalue > 0)
printf(" error code returned = %ld ",rvalue);
printf(" Severity = %d \n",severity);
fflush(stdout);
if (severity > 0)
mt_terminate_program();
}
/* --------------------------------------------------------------------------------------- */
/*
* After a file/link/symlink/dir creation has failed, see if
* it's because some required directory was not present, and if
* so, create all required dirs.
*/
int
make_dirs (pathname)
char *pathname;
{
char *p; /* Points into path */
int madeone = 0; /* Did we do anything yet? */
int save_errno = errno; /* Remember caller's errno */
int check;
// if (errno != ENOENT)
// return 0; /* Not our problem */
for (p = strchr (pathname, '\\'); p != NULL; p = strchr (p + 1, '\\'))
{
/* Avoid mkdir of empty string, if leading or double '/' */
if (p == pathname || p[-1] == '/')
continue;
/* Avoid mkdir where last part of path is '.' */
if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
continue;
*p = 0; /* Truncate the path there */
check = _mkdir (pathname); /* Try to create it as a dir */
if (check == 0)
{
if (debug)
{
printf("made directory %s \n",pathname);
fflush(stdout);
}
madeone++; /* Remember if we made one */
*p = '/';
continue;
}
*p = '/';
if (errno == EEXIST) /* Directory already exists */
continue;
/*
* Some other error in the mkdir. We return to the caller.
*/
break;
}
errno = save_errno; /* Restore caller's errno */
return madeone; /* Tell them to retry if we made one */
}
/* --------------------------------------------------------------------------------------- */
HANDLE open_file_for_write(filename)
char filename[360];
{
HANDLE hFile;
int dirsmade;
hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
/* if we fail here assume it is because the path is not there and call our function to
create directories along the path */
/* if it fails after this we are out of luck */
if (debug)
{
printf("create file %s failed calling make dirs to create any missing directories \n",
filename);
fflush(stdout);
}
dirsmade = make_dirs(filename);
/* now try again to open it */
hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("TapeIO:--> Error Could not create file %s num dirs created = %d\n",
filename,dirsmade);
report_error(" ",0,severe); /* process error */
}
else {
if (debug)
{
printf("TapeIO:-->Created file %s \n",filename);
fflush(stdout);
}
return hFile;
}
} /* end of first create failed */
else {
if (debug)
{
printf("TapeIO:-->Created file %s \n",filename);
fflush(stdout);
}
return hFile;
}
}
/* ------------------------------------------------------------------------------------ */
HANDLE open_file_for_set_time(filename)
char filename[360];
{
HANDLE hFile;
hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
if (debug)
{
printf("TapeIO:--> Open file for set time failed error code = %d \n",GetLastError());
fflush(stdout);
return(NULL);
}
}
else return hFile;
}
/* ------------------------------------------------------------------------------------ */
int compress_file(filename,temppath)
char filename[];
char *temppath;
{
char TempFileName[30];
DWORD lcopied = 0;
int rvalue = 0;
char *nameloc;
/* get the temp path */
/* append the temp filename and call gzip to execute and write the temp file name */
/* pass back the compressed file and we will back that up and remove it */
lcopied = GetTempPath(100,temppath);
if (lcopied <= 0)
{
report_error(" Cannot retrieve temporary directory path \n",0,warning);
return(-1);
}
else
{
/* now create a temp name and concat path to name */
rvalue = GetTempFileName(temppath, /* dir. for temp. files */
"NEW", /* temp. filename prefix */
0, /* create unique name w/ sys. time */
(LPTSTR) TempFileName); /* buffer for name */
if (rvalue == 0)
{
report_error(" Getting temp file name for compression \n",GetLastError(),warning);
return(-1);
}
else
{
/* concat path to name */
/* we only need to name form the temp file as it appends \temp\ to it
and we already have the temppath */
nameloc = strrchr(TempFileName,'\\');
/* skip over slash */
++nameloc;
strcat(temppath,nameloc);
if (debug)
{
printf("temp file for compress = %s \n",temppath);
fflush(stdout);
}
/* now create command to run zip having output go to tempfile. */
//strcpy(cmd, "gzip -c1n "); /* use "gzip -c" for zwrite */
//strncat(cmd, filename, sizeof(cmd)-strlen(cmd));
//strcat(cmd," > ");
//strcat(cmd, temppath);
//if (debug)
// {
// printf("command for gzip = %s \n",cmd);
// fflush(stdout);
// }
rvalue = gzip_compress(filename,temppath);
if (rvalue != 0)
{
mt_report_error("Call to execute compression failed ",rvalue,severe);
return(-1);
}
else return(0);
} /* ok temp name */
} /* ok temp path name */
}
/* ------------------------------------------------------------------------------------ */
int decompress_file(filename,temppath)
char filename[];
char temppath[];
{
int rvalue = 0;
HANDLE tHandle;
/* open the file to make sure it can be created or force creation of paths */
tHandle = open_file_for_write(filename);
CloseHandle(tHandle);
/* now create command to run zip having output go from tempfile to original file */
//strcpy(cmd, "gzip -d < "); /* use "gzip -c" for zwrite */
//strncat(cmd, temppath, sizeof(cmd)-strlen(cmd));
//strcat(cmd," > ");
//strcat(cmd, filename);
//if (debug)
// {
// printf("command for gzip = %s \n",cmd);
// fflush(stdout);
// }
rvalue = gzip_decompress(temppath,filename);
return(rvalue);
}
/* ------------------------------------------------------------------------------------ */
void write_setmarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Write %d setmarks \n",no_marks);
fflush(stdout);
}
rvalue = WriteTapemark(hTape, TAPE_SETMARKS,no_marks,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape write setmarks error ",rvalue,severe);
}
/* ------------------------------------------------------------------------------------ */
void write_filemarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
if (set_mark_positioning)
{
write_setmarks(no_marks);
}
else
{
if (debug)
{
printf("Attempting to Write %d filemarks \n",no_marks);
fflush(stdout);
}
rvalue = WriteTapemark(hTape, TAPE_FILEMARKS,no_marks,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape write filemarks error ",rvalue,severe);
}
}
/* ------------------------------------------------------------------------------------ */
void fill_in_todays_date()
{
struct tm *newtime;
long ltime;
time( <ime );
/* Obtain Universal Coordinated Time: */
newtime = gmtime( <ime );
/* now fill in our date string */
sprintf(todays_date,"%2d-%2d-%2d",(newtime->tm_mon)+1,newtime->tm_mday,newtime->tm_year);
if (debug)
{
printf("filled in todays date with %s \n",todays_date);
fflush(stdout);
}
}
/* ------------------------------------------------------------------------------------ */
/* routine to open up the tape drive assumes only 1 tape drive for now */
void open_tape()
{
if (tape_opened == FALSE)
{
hTape = CreateFile(
"\\\\.\\TAPE0", /* name of tape device to open */
GENERIC_READ | GENERIC_WRITE, /* read-write access */
0, /* not used */
0, /* not used */
OPEN_EXISTING, /* required for tape devices */
0, /* not used */
NULL); /* not used */
if (hTape == NULL)
{
report_error("Opening tape device \n",0,1);
}
else
{
if (debug)
{ printf("TapeIO:--> Opened Tape drive.\n");
fflush(stdout);
}
tape_opened = TRUE;
}
}
}
/* ------------------------------------------------------------------------------------ */
/* function to set block size */
void set_block_size(bsize)
unsigned long bsize;
{
DWORD rvalue;
tparms.BlockSize = bsize;
rvalue = SetTapeParameters(hTape,SET_TAPE_MEDIA_INFORMATION,&tparms);
if (rvalue != NO_ERROR)
{
report_error("Setting tape media information ",rvalue,severe);
}
else
{
if (debug)
{
printf("TapeIO:--> Set tape media parameters i.e. blocksize to %ld\n",bsize);
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
/* rewind the tape always wait for resute no immediate mode */
void rewind_tape(immediate)
BOOLEAN immediate;
{
DWORD rvalue;
rvalue = PrepareTape(hTape,TAPE_LOAD,immediate);
if ((!immediate) && (rvalue != NO_ERROR))
{
report_error("rewinding tape ",rvalue,1);
}
else
{
current_tape_block_number = 0;
if (debug)
{
printf("TapeIO:-->Rewound Tape mode = %d\n",immediate);
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
void space_setmarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
DWORD status;
DWORD rvalue2;
if (debug)
{
printf("Attempting to Space %d setmarks\n",no_marks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_SETMARKS,0,no_marks,0,FALSE);
if (rvalue != NO_ERROR)
{
rvalue2 = GetLastError();
status = GetTapeStatus(hTape);
printf(" Tape positioning by setmarks error rvalue = %d tape status =%d getlsterror = %d\n",
rvalue,status,rvalue2);
fflush(stdout);
report_error(" ",0,severe);
}
}
/* ------------------------------------------------------------------------------------ */
void space_filemarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
DWORD status;
DWORD rvalue2;
if (set_mark_positioning)
{
space_setmarks(no_marks);
}
else {
if (debug)
{
printf("Attempting to Space %d file marks\n",no_marks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_FILEMARKS,0,no_marks,0,FALSE);
if (rvalue != NO_ERROR)
{
rvalue2 = GetLastError();
status = GetTapeStatus(hTape);
printf(" Tape positioning by filemarks error rvalue = %d tape status =%d getlsterror = %d\n",
rvalue,status,rvalue2);
fflush(stdout);
report_error(" ",0,severe);
}
}
}
/* ---------------------------------------------------------------------------------- */
void read_tape_block(buff)
char *buff;
{
DWORD rdflag;
rdflag = ReadFile(hTape, (LPSTR) buff, buffersize, &dwBytesRead, NULL);
/* handle strange error case of not spacing over file mark correctly if on
top of on assume it didn't space write and space over it */
if (rdflag != TRUE)
{
if ((reading_header) && (GetLastError() == ERROR_NO_DATA_DETECTED))
{ /* tape is not initialized */
printf("ERROR while trying to read the tape header information, \n");
printf(" no data was detected. It appears that this tape \n");
printf(" has not been initialized (LKBACKUP -i) \n");
fflush(stdout);
report_error("Error reading tape",rdflag,severe);
}
else
{
printf("error reading block getlasterror %d getstatus %d \n",
GetLastError(),GetTapeStatus(hTape));
fflush(stdout);
report_error("Error reading tape",0,severe);
}
}
else
{
++current_tape_block_number;
if (debug)
{
printf("TapeIO:--> Read %ld characters from the tape \n",dwBytesRead);
fflush(stdout);
}
}
}
/* ------------------------------------------------------------------------------------ */
void write_tape_block(buff)
char buff[];
{
DWORD wrflag;
DWORD dwBytesWritten;
wrflag = WriteFile(hTape, (LPSTR) buff, buffersize, &dwBytesWritten, NULL);
if (wrflag != TRUE)
{
report_error("Error writing tape",0,warning);
}
else
{
if (debug)
{
printf("TapeIO:--> Wrote %ld characters to the tape block = %d\n",
dwBytesWritten,current_tape_block_number);
fflush(stdout);
}
++current_tape_block_number;
}
}
/* -------------------------------------------------------------------------------- */
DWORD read_file_block(lhfile,buff)
HANDLE lhfile;
char *buff;
{
DWORD rdflag;
DWORD dwBytesRead = 0;
rdflag = ReadFile(lhfile, (LPSTR) buff, buffersize, &dwBytesRead, NULL);
if (rdflag != TRUE)
{
report_error("Error reading file",0,warning);
}
else
{
if (debug)
{
printf("TapeIO:--> Read %ld characters from file \n",dwBytesRead);
fflush(stdout);
}
}
return(dwBytesRead);
}
/* ------------------------------------------------------------------------------------ */
DWORD write_file_block(lhfile,buff,bytes)
HANDLE lhfile;
char *buff;
int bytes;
{
DWORD dwBytesWritten = 0;
DWORD wrflag;
wrflag = WriteFile(lhfile, (LPSTR) buff, (DWORD)bytes, &dwBytesWritten, NULL);
if (wrflag != TRUE)
{
report_error("Error writing file",0,warning);
}
else
{
if (debug)
{
printf("TapeIO:--> Wrote %ld characters to file \n",dwBytesWritten);
fflush(stdout);
}
}
return(dwBytesWritten);
}
/* ------------------------------------------------------------------------------------ */
void dump_header_element(element_number)
int element_number;
{
if (strncmp(raw_tape_header.header[element_number].saveset_name,"EMPTY001_____",13) != 0)
{ /* ok not empty */
printf("%-8d",element_number);
printf("%16s",raw_tape_header.header[element_number].saveset_name);
printf("%13d %15d %8s\n",
raw_tape_header.header[element_number].original_size,
raw_tape_header.header[element_number].compressed_size,
raw_tape_header.header[element_number].date);
fflush(stdout);
}
}
/* ------------------------------------------------------------------------------------ */
void space_end_of_data()
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Space to end of data \n");
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_END_OF_DATA,0,0,0,FALSE);
if (rvalue != NO_ERROR)
{
printf(" Tape positioning to end of data error rvalue = %d \n",rvalue);
fflush(stdout);
report_error(" ",rvalue,severe);
}
}
/* ----------------------------------------------------------------------------------------- */
void read_tape_index()
{
char block[bsize1];
int offset = 0;
int element_number = 0;
int end_element_number = 0;
int block_number = 0;
open_tape();
set_block_size(blocksize);
rewind_tape(FALSE);
save_sets_on_tape = 0;
reading_header = TRUE;
/* retrive the tape id first */
read_tape_block(block);
reading_header = FALSE;
if (strncmp(block,backup_version,12) != 0)
{
/* tape is foreign format */
printf("Warning tape is foreign in format.\n");
printf("You must initialize it first with LKBACKUP -i\n");
fflush(stdout);
rewind_tape(TRUE);
close_tape();
exit(1);
}
/* now get to the tape index */
space_end_of_data();
/* now go back one filemark to get to the beginning of the index */
space_filemarks(-1);
space_filemarks(1);
/* retrieve all blocks of the tape index */
current_tape_block_number = 0;
for (block_number = 0; block_number < blocks_per_header; block_number++)
{
read_tape_block(block);
offset = 0;
if (debug)
{
printf("Retrieved block %d %4096s \n",block_number,block);
fflush(stdout);
}
element_number = (block_number * save_sets_per_block);
end_element_number = element_number + save_sets_per_block;
do
{
sscanf(block + offset,"%16s",raw_tape_header.header[element_number].saveset_name);
offset = offset + 16;
sscanf(block + offset,"%10ud",&raw_tape_header.header[element_number].original_size);
offset=offset+10;
sscanf(block + offset,"%10ud",&raw_tape_header.header[element_number].compressed_size);
offset=offset+12;
sscanf(block + offset,"%8s",&raw_tape_header.header[element_number].date);
offset=offset+8;
if (debug)
{
printf("Current offset = %d \n",offset);
dump_header_element(element_number);
}
++element_number;
} while (element_number < end_element_number);
} /* end for all blocks */
rewind_tape(FALSE);
}
/* ------------------------------------------------------------------------------------ */
void write_tape_id()
{
char block[bsize1];
int offset;
open_tape();
set_block_size(blocksize);
rewind_tape(FALSE);
/* fill in backup version and all blocks info */
offset = sprintf(block,"%12s %8s\0",backup_version,todays_date);
write_tape_block(block); /* force data to be written */
write_filemarks(1);
}
/* ------------------------------------------------------------------------------------- */
void write_tape_index(already_positioned)
BOOLEAN already_positioned;
{
char block[bsize1];
int element_number = 0;
int end_element_number = 0;
int offset = 0;
int block_number = 0;
if (!already_positioned)
{
open_tape();
set_block_size(blocksize);
/* space to end of tape data */
rewind_tape(FALSE);
space_end_of_data();
}
current_tape_block_number = 0;
for (block_number = 0; block_number < blocks_per_header; block_number++)
{
offset = 0;
for (element_number = (block_number * save_sets_per_block); element_number < (save_sets_per_block * (block_number + 1)); element_number++)
{
offset = offset + sprintf(block + offset,"%16s%10u %10u %8s",
raw_tape_header.header[element_number].saveset_name,
raw_tape_header.header[element_number].original_size,
raw_tape_header.header[element_number].compressed_size,
raw_tape_header.header[element_number].date);
}
if (debug)
printf("TapeIO:--> character count in buffer = %d\n",offset);
write_tape_block(block);
if (debug)
{
printf("wrote block %d %4096s \n",block_number,block);
fflush(stdout);
}
} /* end for loop */
/* write the file mark after the index */
rewind_tape(TRUE);
}
/* ----------------------------------------------------------------------------- */
void fill_in_header_element(name,osize,csize,date,element_number)
char name[18];
unsigned int osize;
unsigned int csize;
char date[9];
int element_number;
{
strncpy(raw_tape_header.header[element_number].saveset_name,name,16);
raw_tape_header.header[element_number].original_size = osize;
raw_tape_header.header[element_number].compressed_size = csize;
strncpy(raw_tape_header.header[element_number].date,date,8);
raw_tape_header.header[element_number].date[8] = '\0';
}
/* ----------------------------------------------------------------------------------------- */
void clear_header()
{
int element_number;
for (element_number = 0; element_number< max_save_sets; element_number++)
fill_in_header_element("EMPTY001______________________",0,0,"00-00-00",element_number);
}
/* ------------------------------------------------------------------------------------------- */
void initialize_tape()
{
if (debug)
{
printf("TapeIO:--> Initializing Tape.\n");
fflush(stdout);
}
open_tape();
rewind_tape(FALSE);
write_tape_id();
clear_header();
write_tape_index(TRUE);
}
/* ------------------------------------------------------------------------------------------- */
void catalog_tape(no_good_backups)
char *no_good_backups;
{
int no_backups;
int rvalue;
int element_number;
char current_name[40];
char current_number[4];
rvalue = sscanf(no_good_backups,"%d",&no_backups);
if (rvalue == 0)
{
printf("Error %s is not a legal integer value for the number of good backups on the tape \n",
no_good_backups);
fflush(stdout);
report_error(" ",0,severe);
}
/* check for legal number */
if ((no_backups < 1) || (no_backups > max_save_sets))
{
printf("Error %d is not a legal integer value for the number of good backups on the tape \n",
no_backups);
fflush(stdout);
report_error(" ",0,severe);
}
/* otherwise do it */
/* fill in the correct number in the header */
clear_header();
for (element_number = 0; element_number < no_backups; element_number++)
{
strcpy(current_name,"saveset");
sprintf(current_number,"%d",element_number+1);
strcat(current_name,current_number);
while (strlen(current_name) < 30)
strcat(current_name," ");
if (debug)
{
printf("Filling in header with %s for saveset name len = %d \n",current_name,
strlen(current_name));
fflush(stdout);
}
fill_in_header_element(current_name,0,0,"00-00-00",element_number);
} /* end of loop */
/* now space to end of data and write out the index file again */
if (!quiet_mode)
{
printf("Attempting to restore the tape index\n");
fflush(stdout);
}
if (debug)
{
printf("TapeIO:--> Initializing Tape.\n");
fflush(stdout);
}
write_tape_index(FALSE);
}
/* ------------------------------------------------------------------------------------ */
void erase_tape(secure)
BOOLEAN secure;
{
DWORD rvalue;
open_tape();
rewind_tape(FALSE);
current_tape_block_number = 0;
if (secure)
rvalue = EraseTape(hTape,TAPE_ERASE_LONG,FALSE);
else rvalue = EraseTape(hTape,TAPE_ERASE_SHORT,FALSE);
if (rvalue != NO_ERROR)
{
report_error("Erasing tape ",rvalue,severe);
}
else
{
if (debug)
{
printf("TapeIO:-->Erased Tape");
if (secure)
printf(" Secure/long \n");
else printf(" Short \n");
fflush(stdout);
}
rewind_tape(TRUE);
}
}
/* ------------------------------------------------------------------------------------ */
HANDLE open_file_for_read(filename,doing_backup_restore)
char filename[200];
BOOLEAN doing_backup_restore;
{
HANDLE hFile;
hFile = CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_BACKUP_SEMANTICS,(HANDLE)NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("TapeIO:--> Error Could not open file %s\n",filename);
fflush(stdout);
if (doing_backup_restore)
{
return(NULL);
}
else
report_error(" ",0,severe); /* process error */
}
else {
if (debug)
{
printf("TapeIO:-->Opened file %s \n",filename);
fflush(stdout);
}
return hFile;
}
}
/* --------------------------------------------------------------------------------------- */
void open_index_file()
{
DWORD lcopied = 0;
int rvalue = 0;
char TempName[40];
char *nameloc;
if (!tempindexfileopen)
{
lcopied = GetTempPath(100,TempIndexFileName);
if (lcopied <= 0)
report_error(" Cannot retrieve temporary directory path \n",0,severe);
else
{
/* now create a temp name and concat path to name */
rvalue = GetTempFileName(TempIndexFileName, /* dir. for temp. files */
"NEW", /* temp. filename prefix */
0, /* create unique name w/ sys. time */
(LPTSTR) TempName); /* buffer for name */
if (rvalue == 0)
report_error(" Getting temp file name for index file \n",rvalue,severe);
else
{
/* concat path to name */
/* we only need to name form the temp file as it appends \temp\ to it
and we already have the temppath */
nameloc = strrchr(TempName,'\\');
/* skip over slash */
++nameloc;
strcat(TempIndexFileName,nameloc);
TempIndexFile = fopen(TempIndexFileName,"w");
if (TempIndexFile == NULL)
report_error(" Could not create temporary index file.",0,severe);
else
{
if (debug)
{
printf("created temp index file %s \n",TempIndexFileName);
fflush(stdout);
}
tempindexfileopen = TRUE;
}
} /* name ok */
} /* path ok */
} /* not already open */
}
/* --------------------------------------------------------------------------------------- */
void write_index_entry(fpath,size,compressed_size,date,start_block)
char fpath[512];
unsigned int size;
unsigned int compressed_size;
char date[9];
int start_block;
{
int compression_percent = (int)(100.00 * (1.000 - (float)((float)compressed_size/(float)size)));
if ((compressed_size == 0) && (size > 0))
compression_percent = 0;
if (!tempindexfileopen)
open_index_file();
/* write info to command line and then to index file */
if (!quiet_mode)
{
printf("%s %d %d (%d)%% %8s %d\n",
fpath,size,compressed_size,compression_percent,date,start_block);
}
fprintf(TempIndexFile,"%350s %10d %10d %8s %10d \n",
fpath,size,compressed_size,date,start_block);
fflush(stdout);
fflush(TempIndexFile);
}
/* --------------------------------------------------------------------------------------*/
void close_index_file()
{
if (tempindexfileopen)
{
fclose(TempIndexFile);
if (debug)
{
printf("closed temp index file \n");
fflush(stdout);
}
tempindexfileopen = FALSE;
}
}
/* --------------------------------------------------------------------------------------*/
void mt_compress_file(filename,size)
char filename[];
DWORD size;
{
char lbuffer[bsize1];
HANDLE hFile;
LPTSTR ppszFilePart; /* address of filename in path */
DWORD rvalue;
FILETIME wtime;
BOOLEAN oktime;
DWORD dwAttrs;
char savepath[513];
int ldwBytesRead = 0;
char compress_name[500];
char fnamecopy[500];
int queue_elements;
READ_QUEUE_TYPE element;
BOOLEAN compressed = FALSE;
BOOLEAN compressed_ok = FALSE;
strcpy(fnamecopy,lbuffer);
hFile = open_file_for_read(filename,TRUE);
if (hFile == NULL) /* skip it since it couldn't be opened */
{
++filesskipped;
printf("Warning skipping file %s which could not be opened. \n",filename);
fflush(stdout);
}
else
{
if (debug_child)
{
printf("TapeIO:--> In child thread Attempting to compress %s size is %ld \n",filename,size);
fflush(stdout);
}
/* write full path to file */
/* but erase first 3 chars ie i:\ so that restore is not drive specific */
rvalue = GetFullPathName((LPCSTR)filename,buffersize,(LPTSTR)lbuffer,&ppszFilePart);
if (rvalue == 0)
{
CloseHandle(hFile);
printf("Warning skipping file %s because full path and filename is longer than 512 chars \n",filename);
fflush(stdout);
++filesskipped;
}
else
{
strcpy(fnamecopy,lbuffer);
lbuffer[0] = ' ';
lbuffer[1] = ' ';
lbuffer[2] = ' ';
strcpy(savepath,lbuffer);
if (debug_child)
{
printf("TapeIO:--> Attempting to compress %s size is %ld \n",savepath,size);
fflush(stdout);
}
/* now write file date/time and attributes */
oktime = GetFileTime(hFile,NULL,NULL,&wtime);
if (!oktime)
report_error(" Couldn't retrieve file time \n",0,warning);
/* get attr string */
dwAttrs = GetFileAttributes(filename);
sprintf(lbuffer + rvalue," %d %d %d %d",size,dwAttrs,
wtime.dwLowDateTime,wtime.dwHighDateTime);
CloseHandle(hFile);
/* only compress if below threshold size to try and keep tape streaming */
if (((size < compress_threshold) && (size > (DWORD)blocksize)) && (want_compression))
{
compressed = TRUE;
rvalue = compress_file(filename,&compress_name);
if (debug_child)
{
printf("rvalue from compression = %d \n",rvalue);
fflush(stdout);
}
if (rvalue == 0)
{
compressed_ok = TRUE;
/* file was compressed ok so log the stuff to the queue and go on */
if (debug_child)
{
printf("file %s compressed correctly temp name = %s\n",filename,compress_name);
fflush(stdout);
}
}
else
{
compressed_ok = FALSE;
}
}
else
{
compressed = FALSE;
/* copy name */
strcpy(compress_name,fnamecopy);
}
if ((!compressed) || (compressed_ok))
{
/* now attempt to put it in the queue and go on as long as the queue is not too full
if it is too full sleep and try again */
queue_elements = 0;
do
{
queue_elements = read_elements_in_queue();
if (queue_elements >= 29)
{
/* wait */
Sleep(500);
if (debug_child)
{
printf("Woke up from .5 second wait queue size was %d \n",queue_elements);
fflush(stdout);
}
}
} while (queue_elements >= 29);
/* if we got here there is room in the queue to do it */
strcpy(element.original_filename,savepath);
strcpy(element.temp_filename,compress_name);
element.size = size;
element.attrs = dwAttrs;
element.lowdate = wtime.dwLowDateTime;
element.highdate = wtime.dwHighDateTime;
element.compressed = compressed;
if (debug_child)
{
printf("Filled in element with: \n");
printf("original name = %s \n",element.original_filename);
printf("temp name = %s \n",element.temp_filename);
printf("size = %d attrs = %d lowdate = %d highdate = %d \n",
element.size,element.attrs,element.lowdate,element.highdate);
fflush(stdout);
}
push_element(element);
} /* compressed ok or not compressed */
} /* path ok */
} /* opened ok */
}
/* --------------------------------------------------------------------------------------*/
void backup_index_file(filename,size,attributes)
char filename[];
DWORD size;
{
char lbuffer[bsize1];
HANDLE hFile;
LPTSTR ppszFilePart; /* address of filename in path */
DWORD rvalue;
int start_block = current_tape_block_number;
int ldwBytesRead = 0;
hFile = open_file_for_read(filename,TRUE);
/* now since file opened ok write out first buffer with file name and
size */
if (hFile == NULL) /* skip it since it couldn't be opened */
{
++filesskipped;
printf("Warning skipping file %s which could not be opened. \n",filename);
fflush(stdout);
}
else
{
if (debug)
{
printf("TapeIO:--> Backing up %s size is %ld \n",filename,size);
fflush(stdout);
}
/* write full path to file */
/* but erase first 3 chars ie i:\ so that restore is not drive specific */
rvalue = GetFullPathName((LPCSTR)filename,buffersize,(LPTSTR)lbuffer,&ppszFilePart);
if (rvalue == 0)
{
CloseHandle(hFile);
report_error(" Path + file name longer than max buffer size (512)\n",rvalue,severe);
}
lbuffer[0] = ' ';
lbuffer[1] = ' ';
lbuffer[2] = ' ';
if (debug)
{
printf("TapeIO:--> Backing up %s size is %ld \n",lbuffer,size);
fflush(stdout);
}
sprintf(lbuffer + rvalue," %d %d %d %d",size,0,
0,0);
write_tape_block(lbuffer);
if (debug)
{
printf("wrote block for file header %2048s \n",lbuffer);
fflush(stdout);
}
do {
dwBytesRead = read_file_block(hFile,lbuffer);
if (dwBytesRead > 0)
{
if (debug)
{
printf("TapeIO:-->Attempting to write the buff to tape\n");
fflush(stdout);
}
write_tape_block(lbuffer);
} /* bytes > 0 */
} while (dwBytesRead == buffersize);
/* close the file handle */
CloseHandle(hFile);
++filesuncompressed;
total_backup_size = total_backup_size + size;
total_original_size = total_original_size + size;
} /* skip file */
}
/* --------------------------------------------------------------------------------------*/
void mt_backup_files()
/* modify routine to simply read queue element and backup the file if not index file
and compression on */
{
char lbuffer[bsize1];
HANDLE hFile, hMapHandle;
unsigned int compress_size = 0;
int elements_in_queue;
READ_QUEUE_TYPE element;
FILETIME wtime;
unsigned short dostime;
unsigned short dosdate;
char file_date[9];
int start_block = current_tape_block_number;
BOOLEAN mapok = FALSE;
LPVOID memory_address = NULL;
DWORD fsize;
int compress_size_to_write = 0;
BOOLEAN skipping_file = FALSE;
BOOLEAN old_method_ok = FALSE;
BOOLEAN unmap_ok = FALSE;
/* lgk add case to handle uncompressed file below threshold and to turn off file mapping */
elements_in_queue = 0;
do /* loop until we are signaled that we are done and there are no more elements to be processed */
{
/* get element from queue if it is waiting if not sleep for two seconds and try again */
do /* loop while there are no elements to process and we are not done */
{
elements_in_queue = read_elements_in_queue();
if ((elements_in_queue == 0) && (!processed_all_files))
Sleep(500);
} while ((elements_in_queue == 0) && (!processed_all_files));
/* now that we have an item read it */
/* need to read it again here because between the time elements was 0 and the end of
the while loop processed_all_files is getting set to true and the loop is exiting
without realizing about the last few files in the queue */
elements_in_queue = read_elements_in_queue();
if (elements_in_queue > 0)
{
element = pop_element();
/* now process_it */
compress_size = 0;
start_block = current_tape_block_number;
if (debug)
{
printf("TapeIO:--> Backing up %s aka %s size is %ld \n",
element.original_filename,element.temp_filename,element.size);
fflush(stdout);
}
skipping_file = FALSE;
old_method_ok = FALSE;
mapok = FALSE;
memory_address = NULL;
hFile = open_file_for_read(element.temp_filename,TRUE);
if (hFile == NULL) /* skip it since it couldn't be opened */
{
++filesskipped;
printf("Warning skipping file %s since temp file/tempfile %s could not be opened. \n",
element.original_filename,element.temp_filename);
fflush(stdout);
skipping_file = TRUE;
mapok = FALSE;
}
else /* skipping */
{
sprintf(lbuffer,"%350s %d %d %d %d",element.original_filename,element.size,element.attrs,
element.lowdate,element.highdate);
write_tape_block(lbuffer);
if (debug)
{
printf("wrote block for file header %2048s \n",lbuffer);
fflush(stdout);
}
/* only use file mapping if on */
if (file_mapping)
{
mapok = TRUE;
/* lgk new code here to speed things up by reading the entire file into a memory
buffer and then writting to tape if this fails default to the old method */
/* get the file size */
fsize = GetFileSize(hFile,NULL);
if (fsize == 0xFFFFFFFF)
{
if (debug)
{
printf("Getfile size for %s failed \n",element.temp_filename);
fflush(stdout);
CloseHandle(hFile);
mapok = FALSE;
}
}
else
{
hMapHandle = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,"compress_map");
if (hMapHandle == NULL)
{
if (debug)
{
printf("Map file did not open correctly rvalue = %d \n",GetLastError());
fflush(stdout);
CloseHandle(hFile);
mapok = FALSE;
}
}
else
{
/* now map the handle into memory */
memory_address = MapViewOfFile(hMapHandle,FILE_MAP_READ,0,0,0);
if (memory_address == NULL)
{
printf("Map file view did not open correctly rvalue = %d \n",GetLastError());
fflush(stdout);
CloseHandle(hFile);
CloseHandle(hMapHandle);
mapok = FALSE;
}
else
{
/* ok now process the memory in blocks that the tape drive can handle */
compress_size = 0;
mapok = TRUE;
do
{
write_tape_block((char *)((DWORD)(memory_address) + compress_size));
compress_size = compress_size + buffersize;
} while (compress_size < fsize);
/* ok reset compress_size which got too big */
compress_size = fsize;
} /* ok address */
} /* ok handle */
} /* ok size */
/* clean up if worked ok otherwise try other method */
if (mapok)
{
if (debug)
{
printf("file map method worked \n");
fflush(stdout);
}
unmap_ok = TRUE;
unmap_ok = UnmapViewOfFile(memory_address);
if (!unmap_ok)
{
printf("Warning unmapping of file view failed error code = %d \n",GetLastError());
fflush(stdout);
}
/* now close the handles */
CloseHandle(hMapHandle);
CloseHandle(hFile);
} /* mapped ok */
} /* end file mapping on */
else /* either it failed or don't want file mapping */
{
do {
dwBytesRead = read_file_block(hFile,lbuffer);
if (dwBytesRead > 0)
{
if (debug)
{
printf("TapeIO:-->Attempting to write the buff to tape\n");
fflush(stdout);
}
write_tape_block(lbuffer);
compress_size = compress_size + dwBytesRead;
} /* bytes > 0 */
} while (dwBytesRead == buffersize);
/* close the file handle */
CloseHandle(hFile);
old_method_ok = TRUE;
} /* end of old method */
if (old_method_ok || mapok)
{
/* now handle the index entry */
wtime.dwLowDateTime = element.lowdate;
wtime.dwHighDateTime = element.highdate;
/* need to convert to file date for the index entry */
if (element.compressed)
{
compress_size_to_write = compress_size;
total_backup_size = total_backup_size + compress_size;
}
else
{
compress_size_to_write = 0;
total_backup_size = total_backup_size + element.size;
}
if (!FileTimeToDosDateTime(&wtime,&dosdate,&dostime))
{
printf("Warning couldn't convert file date to dos date using todays date \n");
fflush(stdout);
write_index_entry(element.original_filename,element.size,compress_size_to_write,
todays_date,start_block);
}
/* ok we got the date no set it into varibles and convert to string */
else
{
int nDay = dosdate & 0x1f;
int nMonth = (dosdate >> 5) & 0x0f;
int nYear = (dosdate >> 9) + 80;
/* now convert to string */
sprintf(file_date,"%02d-%02d-%02d",nMonth,nDay,nYear);
write_index_entry(element.original_filename,element.size,compress_size_to_write,
file_date,start_block);
}
/* only delete file if actually was temp file don't do it for uncompressed files */
if (element.compressed)
{
++filescompressed;
DeleteFile(element.temp_filename);
}
else ++filesuncompressed;
total_original_size = total_original_size + element.size;
} /* mpa ok or old meethod ok */
} /* not skipping file */
} /* we have an element */
} while ((elements_in_queue != 0) || (!processed_all_files));
}
/* ------------------------------------------------------------------------------------- */
void set_file_info(filename,lowtime,hightime,lattrs)
char *filename;
DWORD lowtime;
DWORD hightime;
DWORD lattrs;
{
FILETIME local_file_time;
HANDLE writeHandle;
/* attempt to set date and file attributes */
if (lattrs != 0)
{
if (debug)
{
printf("Attempting to set file attributes to %d \n",lattrs);
fflush(stdout);
}
if (!SetFileAttributes(filename,lattrs))
{
printf("Warning couldn't set file %s attributes to %s during restore \n",filename,lattrs);
fflush(stdout);
}
}
/* now fill in a wtime struct and attempt to reset the time */
local_file_time.dwLowDateTime = lowtime;
local_file_time.dwHighDateTime = hightime;
writeHandle = open_file_for_set_time(filename);
if (!SetFileTime(writeHandle,NULL,NULL,&local_file_time))
{
printf("Warning couldn't set file last write time for %s error = %d \n",
filename,GetLastError());
fflush(stdout);
}
CloseHandle(writeHandle);
}
/* --------------------------------------------------------------------------------------*/
void restore_file(filename,size,csize,isindexfile)
char *filename;
int size;
int csize;
BOOLEAN isindexfile;
/* return the restored file name */
/* if it is the index file create it as orinally but append the temp drive to it */
{
char temppath[400];
BOOLEAN compressed = FALSE;
char lbuffer[bsize1];
HANDLE hFile;
int restore_size;
DWORD lcopied = 0;
unsigned int rvalue2;
char TempFileName[400];
char *nameloc;
BOOLEAN done;
int size_restored_so_far = 0;
char lname[400];
DWORD lowtime;
DWORD hightime;
DWORD lattrs;
int lsize;
if (csize > 0)
{
compressed = TRUE;
restore_size = csize;
/* create a temp file name/path to restore the file to */
} /* compress */
else
{
compressed = FALSE;
restore_size = size;
}
/* get the temp path for a compress restore or restore of the index file */
if (compressed || isindexfile)
{
lcopied = GetTempPath(100,temppath);
if (lcopied <= 0)
{
report_error(" Cannot retrieve temporary directory path \n",0,severe);
}
else
{
/* now create a temp name and concat path to name */
rvalue2 = GetTempFileName(temppath, /* dir. for temp. files */
"NEW", /* temp. filename prefix */
0, /* create unique name w/ sys. time */
(LPTSTR) TempFileName); /* buffer for name */
if (rvalue2 == 0)
{
report_error(" Getting temp file name for decompression \n",rvalue2,severe);
}
else
{
/* concat path to name */
/* we only need to name form the temp file as it appends \temp\ to it
and we already have the temppath */
nameloc = strrchr(TempFileName,'\\');
/* skip over slash */
++nameloc;
strcat(temppath,nameloc);
if (debug)
{
printf("temp file for decompress = %s \n",temppath);
fflush(stdout);
}
} /* name ok */
} /* path ok */
} /* for index or compressed file */
else
{
/* not compressed or index means regular file uncompressed to copy file name to temppath */
strcpy(temppath,filename);
}
if (debug)
{
printf("TapeIO:--> Restoring file about to read name block \n");
fflush(stdout);
}
read_tape_block(lbuffer);
if (debug)
{
printf("In restore file got name block number %s\n",lbuffer);
fflush(stdout);
}
if (isindexfile)
{
/* get the size out of the buffer */
sscanf(lbuffer,"%350s %10d",filename,&size);
restore_size = size; /* index file is not compressed */
if (debug)
{
printf("got name/size for index file name = %s size = %d \n",filename,size);
fflush(stdout);
}
}
/* check to make sure name in file matches restore name ignore check for index file */
else
{ /* must skip over first 3 characters in buffer that had e:\ etc. in it */
/* get times and attributes */
lsize = 0;
lattrs = 0;
lowtime = 0;
hightime = 0;
sscanf(lbuffer + 3,"%s %d %d %d %d",lname,&lsize,&lattrs,&lowtime,&hightime);
if (strncmp(filename,lname,strlen(filename)) != 0)
{
printf("Tape IO Error Name in buffer %350s does not match restore file name %s \n",
lbuffer,filename);
fflush(stdout);
report_error(" ",0,severe);
}
}
/* now restore the file wherever (to temppath) */
if (debug)
{
printf("attempting to open for write/restore: %s \n",temppath);
fflush(stdout);
}
hFile = open_file_for_write(temppath);
done = FALSE;
size_restored_so_far = 0;
/* problem here for file of 0 length we don't want to read the block or we are off when
it comes to the next file since a block was not written out */
/* restore the file pointed to by hfile */
if (restore_size > 0)
{
do {
read_tape_block(lbuffer);
if (debug)
{
printf("TapeIO:-->Attempting to write the buff to file\n");
fflush(stdout);
}
if ((size_restored_so_far + blocksize) <= restore_size)
{
write_file_block(hFile,lbuffer,blocksize);
if ((size_restored_so_far + blocksize) == restore_size)
done = TRUE;
size_restored_so_far = size_restored_so_far + blocksize;
}
else /* write last partial block */
{
write_file_block(hFile,lbuffer,restore_size - size_restored_so_far);
if (debug)
{
printf("Writing out last partial block of %d characters \n",
restore_size - size_restored_so_far);
fflush(stdout);
}
done = TRUE;
size_restored_so_far = size_restored_so_far + (restore_size - size_restored_so_far);
} /* bytes > 0 */
} while (!done);
} /* end of size > 0 */
/* close the file handle */
CloseHandle(hFile);
/* now if the file was uncompressed or the index file
we are done otherwise if it was compressed we need to decompress it to the
original file */
if (!compressed)
{
if (!isindexfile)
set_file_info(filename,lowtime,hightime,lattrs);
if ((!quiet_mode) && (!isindexfile))
{
printf("Restored Uncompressed file %s \n",filename);
fflush(stdout);
}
++filesuncompressed;
total_bytes_read = total_bytes_read + size;
/* if index file copy name to ifle name */
if (isindexfile)
strcpy(filename,temppath);
}
else /* compressed */
{
/* now decompress it */
/* when decompressing the name somehow gets changes to / probably in the mkdir
routine can't find it so copy it, and copy back after decompress */
strcpy(lname,filename);
if (decompress_file(filename,temppath) == -1)
{
printf("Warning couldn't decompress file %s \n",lname);
printf("File NOT RESTORED \n");
printf("Leaving temp file %s for an attempt at manual decompression. \n",temppath);
fflush(stdout);
}
else
{
/* copy back */
strcpy(filename,lname);
set_file_info(filename,lowtime,hightime,lattrs);
if (!quiet_mode)
{
printf("Restored Compressed file %s\n",filename);
fflush(stdout);
}
++filescompressed;
total_bytes_read = total_bytes_read + csize;
DeleteFile(temppath);
}
}
}
/* -------------------------------------------------------------------------------------- */
void print_backup_stats()
{
DWORD total_time;
unsigned long int minutes;
unsigned long int backuprate;
total_time = GetTickCount() - start_time;
if (debug)
printf("total time = %d \n",total_time);
minutes = (int)(((float)total_time) / ((float)60000.0000));
/* 60 * 1000 which equal the number
of milliseconds in a minute */
backuprate = (int)(((float)total_original_size / (float)minutes) / (float)1024.000);
if (!quiet_mode)
{
printf("\n----------------------------------------------------------------\n");
printf("Files Backed Up --> %d \n",filescompressed+filesuncompressed);
printf(" No Compressed --> %d \n",filescompressed);
printf(" No UnCompressed --> %d \n",filesuncompressed);
printf("Files Skipped --> %d \n\n",filesskipped);
printf("Original Size --> %d \n",total_original_size);
printf("Size on Tape --> %d \n",total_backup_size);
printf("Compression Ratio --> (%2d%%)\n\n",
(int)(100.00 * (1.000 - (float)((float)total_backup_size/(float)total_original_size))));
printf("Backup Time (minutes) --> %d \n",minutes);
printf("Backup Rate K/minute --> %d \n",backuprate);
printf("\n----------------------------------------------------------------\n");
fflush(stdout);
}
}
/* --------------------------------------------------------------------------------------- */
void print_restore_stats()
{
DWORD total_time;
unsigned long int minutes;
unsigned long int restoreuprate;
total_time = GetTickCount() - start_time;
if (debug)
printf("total time = %d \n",total_time);
minutes = (int)(((float)total_time) / ((float)60000.0000));
/* 60 * 1000 which equal the number
of milliseconds in a minute */
restoreuprate = (int)(((float)total_bytes_read / (float)minutes) / (float)1024.000);
if (!quiet_mode)
{
printf("\n----------------------------------------------------------------\n");
printf("Files Restored --> %d \n",filescompressed+filesuncompressed);
printf(" No Compressed --> %d \n",filescompressed);
printf(" No UnCompressed --> %d \n\n",filesuncompressed);
printf("Total Bytes Restored --> %d \n",total_bytes_read);
printf("Restore Time (minutes) --> %d \n",minutes);
printf("Restore Rate K/minute --> %d \n",restoreuprate);
printf("\n----------------------------------------------------------------\n");
fflush(stdout);
}
}
/* --------------------------------------------------------------------------------------- */
void write_directory_file()
{
int fsize;
fsize = ftell(TempIndexFile);
close_index_file();
/* size is not important for this file */
/*ignore drive letter on file */
/* we need the file size here otherwise it will not know how much to restore */
backup_index_file(TempIndexFileName,fsize);
/* now delete the file */
DeleteFile(TempIndexFileName);
}
/* ----------------------------------------------------------------------------------- */
void process_write_directory(SearchString,process_subdirs)
char *SearchString;
BOOLEAN process_subdirs;
/* if process subdirs set first go through entire directory then do it again and process subdirs */
{
WIN32_FIND_DATA FileData;
HANDLE hSearch;
BOOLEAN done = FALSE;
BOOLEAN rvalue;
BOOLEAN onefound = FALSE;
/* Start searching for files in the current directory. */
hSearch = FindFirstFile(SearchString, &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
/* no files in search parameters */
if ((debug) && (!process_subdirs))
{
printf("TapeIO:--> Warning no files found in search parameter %s \n",SearchString);
fflush(stdout);
}
if (!process_subdirs)
{
FindClose(hSearch);
return; /* cannot do this directory */
}
}
else onefound = TRUE;
if (onefound)
{
/* get size and process file only gets here if handle opened ok */
/* skip directories */
if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
mt_compress_file(FileData.cFileName,FileData.nFileSizeLow);
/* loop through remainder of files */
do {
rvalue = FindNextFile(hSearch,&FileData);
if ((rvalue == FALSE) && (GetLastError() == ERROR_NO_MORE_FILES))
{
done = TRUE;
FindClose(hSearch);
}
else
{
if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
mt_compress_file(FileData.cFileName,FileData.nFileSizeLow);
}
} while (!done);
} /* onefound */
/* now if process subdirs set go through and stop at all subdirs and recurse */
if (process_subdirs)
{
done = FALSE;
/* Start searching for all subdirectories to recurse on */
hSearch = FindFirstFile("*", &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
FindClose(hSearch);
return; /* cannot do this directory */
} /* no files */
/* now check if file is subdir if so process if it is not "." or ".." */
if ((strncmp(FileData.cFileName,".",1) != 0) &&
(strncmp(FileData.cFileName,"..",2) != 0))
{
/* ok is not bs names */
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (SetCurrentDirectory(FileData.cFileName) == FALSE)
{
printf("TapeIO:--> Warning Couldn't change directory to %s \n",FileData.cFileName);
fflush(stdout);
}
else {
process_write_directory(SearchString,process_subdirs);
/* set current directory back */
SetCurrentDirectory("..");
}
} /* is directory */
} /* is not . or .. */
/* when it returns recurse through remainder of subdirs */
do
{
rvalue = FindNextFile(hSearch,&FileData);
if ((rvalue == FALSE) && (GetLastError() == ERROR_NO_MORE_FILES))
{
done = TRUE;
FindClose(hSearch);
}
else
{
/* now check if file is subdir if so process if it is not "." or ".." */
if ((strncmp(FileData.cFileName,".",1) != 0) &&
(strncmp(FileData.cFileName,"..",2) != 0))
{
/* ok is not bs names */
/* instead of using getfileattrs dwFileAttributes */
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/* is a directory so set directory and recurse */
if (SetCurrentDirectory(FileData.cFileName) == FALSE)
{
printf("TapeIO:--> Warning Couldn't change directory to %s \n",FileData.cFileName);
fflush(stdout);
}
else {
process_write_directory(SearchString,process_subdirs);
SetCurrentDirectory("..");
}
} /* is directory */
} /* is not . or .. */
} /* else not last file */
} while (!done);
} /* process subdirs */
}
/* ------------------------------------------------------------------------------------------ */
void mt_process_write_directory(LPVOID dummy)
{
/* call read process write directory */
/* get the global values */
if (debug_child)
{
printf("in top level mt process write directory search string = %s subdirs = %d \n",
Global_SearchString,global_process_subdirs);
fflush(stdout);
}
process_write_directory(Global_SearchString,global_process_subdirs);
if (debug_child)
{
printf("in thread done processing files \n");
fflush(stdout);
}
processed_all_files = TRUE;
thread_active = FALSE;
}
/* ------------------------------------------------------------------------------------ */
void space_sequential_filemarks(no_marks)
DWORD no_marks;
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Space %d Seqential file marks\n",no_marks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_SEQUENTIAL_FMKS,0,no_marks,0,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape positioning by sequential filemarks error ",rvalue,severe);
}
/* ------------------------------------------------------------------------------------ */
void space_scsi_blocks(no_blocks)
DWORD no_blocks;
{
DWORD rvalue;
if (debug)
{
printf("Attempting to Space %d Scsi data blocks \n",no_blocks);
fflush(stdout);
}
rvalue = SetTapePosition(hTape,TAPE_SPACE_RELATIVE_BLOCKS,0,no_blocks,0,FALSE);
if (rvalue != NO_ERROR)
report_error(" Tape positioning by scsi (relative) block error ",rvalue,severe);
}
/* ---------------------------------------------------------------------------------- */
void eject_tape()
{
DWORD rvalue;
rvalue = PrepareTape(hTape,TAPE_UNLOAD,FALSE);
if (rvalue != NO_ERROR)
{
report_error("Ejecting tape ",rvalue,severe);
}
else
{
if (debug)
{
printf("TapeIO:-->Unloaded/Ejected Tape \n");
fflush(stdout);
}
}
}
/* ---------------------------------------------------------------------------------- */
void list_tape()
{
int element_number = 0;
read_tape_index();
printf("Number Saveset Name Original Size Compressed Size Date \n");
printf("__________________________________________________________________\n");
for (element_number = 0; element_number < max_save_sets; element_number++)
dump_header_element(element_number);
printf("\nListing Complete\n\n");
fflush(stdout);
}
/* ------------------------------------------------------------------------------------ */
int find_free_saveset_element()
{
BOOLEAN found = FALSE;
int number = 0;
int element_number = 0;
for (element_number = 0; element_number < max_save_sets; element_number++)
{
if (strncmp(raw_tape_header.header[element_number].saveset_name,"EMPTY001_____",13) == 0)
{
number = element_number;
found = TRUE;
break;
}
}
if (found)
return(number);
else return(-1);
}
/* ------------------------------------------------------------------------------------- */
BOOLEAN get_index_file_entry(indexrec)
INDEX_REC_TYPE *indexrec;
{
int lsize;
int csize;
int sblock;
char ldate[9];
char fname[351];
int rvalue;
rvalue = fscanf(TempIndexFile,"%350s %10d %10d %8s %10d \n",fname,&lsize,&csize,ldate,&sblock);
if (rvalue == 0)
report_error("Reading index file entry \n",0,severe);
if (rvalue == EOF)
{
if (debug)
{
printf("EOF of index file found \n");
fflush(stdout);
}
fclose(TempIndexFile);
return(FALSE);
}
if (debug)
{
printf("Successfully retrieved index entry %s %d %d %8s %d\n",fname,lsize,csize,ldate,sblock);
fflush(stdout);
}
/* fill in fields */
indexrec->original_size = lsize;
indexrec->compressed_size = csize;
strcpy(indexrec->fname,fname);
strcpy(indexrec->date,ldate);
indexrec->start_block = sblock;
if (debug)
{
printf("Successfully filled in index entry %s %d %d %8s %d\n",
indexrec->fname,
indexrec->original_size,
indexrec->compressed_size,
indexrec->date,
indexrec->start_block);
fflush(stdout);
}
return(TRUE);
}
/* -------------------------------------------------------------------------------------- */
void list_index_file(indexfilename2,savesetname2)
char *indexfilename2;
char *savesetname2;
{
INDEX_REC_TYPE indexrec;
BOOLEAN rvalue = FALSE;
/* print header */
printf("Saveset Listing for %s \n",savesetname2);
printf("Original Size Compressed Size Date Start Block Filename\n");
printf("__________________________________________________________________________\n");
/* loop through and get file entry and print out contents */
/* first open up the index file for reading */
TempIndexFile = fopen(indexfilename2,"r");
if (TempIndexFile == NULL)
report_error(" Could not open temporary index file.",0,severe);
else
{
if (debug)
{
printf("opened for read temp index file %s \n",indexfilename2);
fflush(stdout);
}
tempindexfileopen = TRUE;
}
do {
rvalue = get_index_file_entry(&indexrec);
if (rvalue)
{
printf("%10d %10d %8s %10d %-s\n",
indexrec.original_size,
indexrec.compressed_size,
indexrec.date,
indexrec.start_block,
indexrec.fname);
fflush(stdout);
}
} while (rvalue == TRUE);
printf("\nListing Complete\n\n");
fflush(stdout);
}
/* ------------------------------------------------------------------------------------ */
int find_saveset_element(saveset)
char saveset[18];
{
BOOLEAN found = FALSE;
int number = 0;
int element_number = 0;
int slen = strlen(saveset);
for (element_number = 0; element_number < max_save_sets; element_number++)
{
if (strncmp(raw_tape_header.header[element_number].saveset_name,saveset,slen) == 0)
{
number = element_number;
found = TRUE;
break;
}
}
if (found)
return(number);
else return(-1);
}
/* --------------------------------------------------------------------------------------*/
void list_saveset(saveset)
char *saveset[18];
{
int element_number;
char indexfilename[400];
read_tape_index();
rewind_tape(FALSE);
element_number = find_saveset_element(saveset);
if (element_number < 0)
{
printf("Saveset %s Not found on the tape, use LKBACKUP -l for a listing. \n",saveset);
fflush(stdout);
close_tape();
report_error(" ",0,severe);
}
/* now that we found the saveset space to the directory listing and read it */
/* tape id 1
1 data 2 index 3 saveset 0
3 data 4 index 5 saveset 1
5 data 6 index 7 saveset 2
7 data 8 index 9 saveset 3
.
.
.
tape index [filemark]
etc. */
space_filemarks((element_number * 2) + 2);
/* now recreate the file and list it */
restore_file(indexfilename,0,0,TRUE);
list_index_file(indexfilename,saveset);
DeleteFile(indexfilename);
rewind_tape(TRUE);
close_tape();
}
/* --------------------------------------------------------------------------------- */
void process_restore(indexfilename2,search_string)
char *indexfilename2;
char search_string[];
{
/* now go through each line in the index file and check if name matches */
int lsize;
int csize;
int sblock;
char ldate[9];
char fname[351];
int rvalue;
BOOLEAN eof_found = FALSE;
INDEX_REC_TYPE indexrec;
/* first open up the index file for reading */
TempIndexFile = fopen(indexfilename2,"r");
if (TempIndexFile == NULL)
report_error(" Could not open temporary index file.",0,severe);
else
{
if (debug)
{
printf("opened for read temp index file %s \n",indexfilename2);
fflush(stdout);
}
tempindexfileopen = TRUE;
}
do {
rvalue = fscanf(TempIndexFile,"%350s %10d %10d %8s %10d \n",fname,&lsize,&csize,ldate,&sblock);
if (rvalue == 0)
report_error("Reading index file entry \n",0,severe);
if (rvalue == EOF)
{
if (debug)
{
printf("EOF of index file found \n");
fflush(stdout);
}
fclose(TempIndexFile);
eof_found = TRUE;
}
else
{
if (debug)
{
printf("Successfully retrieved index entry %s %d %d %8s %d\n",fname,lsize,csize,ldate,sblock);
fflush(stdout);
}
/* fill in fields */
indexrec.original_size = lsize;
indexrec.compressed_size = csize;
strcpy(indexrec.fname,fname);
strcpy(indexrec.date,ldate);
indexrec.start_block = sblock;
if (debug)
{
printf("Successfully filled in index entry %s %d %d %8s %d\n",
indexrec.fname,
indexrec.original_size,
indexrec.compressed_size,
indexrec.date,
indexrec.start_block);
fflush(stdout);
}
/* now check for match */
if (wild_match(search_string,indexrec.fname))
{
if (debug)
{
printf("match found %s with %s \n",search_string,indexrec.fname);
printf("current block = %d need to be at block %d \n",current_tape_block_number,
indexrec.start_block);
fflush(stdout);
}
if (current_tape_block_number < indexrec.start_block)
{
if (debug)
{
printf("attempting to space forward %d blocks \n",
indexrec.start_block - current_tape_block_number);
fflush(stdout);
}
space_scsi_blocks(indexrec.start_block - current_tape_block_number);
current_tape_block_number = indexrec.start_block;
}
else if (current_tape_block_number > indexrec.start_block)
{
/* error condition */
printf("TapeIO --->: Error tape position of %d > start block of %d shouldn't happen \n",
current_tape_block_number,indexrec.start_block);
fflush(stdout);
report_error(" ",0,severe);
}
/* now restore the file */
restore_file(indexrec.fname,indexrec.original_size,indexrec.compressed_size,FALSE);
} /* end of ok match */
} /* eof not found */
} while (!eof_found);
}
/* --------------------------------------------------------------------------------------*/
void do_restore(saveset,search_string)
char saveset[18];
char search_string[];
{
int element_number;
char indexfilename[400];
total_bytes_read = 0;
filescompressed = 0;
filesuncompressed = 0;
store_start_time();
read_tape_index();
rewind_tape(FALSE);
element_number = find_saveset_element(saveset);
if (element_number < 0)
{
printf("Saveset %s Not found on the tape, use LKBACKUP -l for a listing. \n",saveset);
fflush(stdout);
close_tape();
report_error(" ",0,severe);
}
/* now that we found the saveset space to the directory listing and read it */
/* tape id 1
1 data 2 index 3 saveset 0
3 data 4 index 5 saveset 1
5 data 6 index 7 saveset 2
7 data 8 index 9 saveset 3
.
.
.
tape index [filemark]
etc. */
space_filemarks((element_number * 2) + 2);
/* now recreate the file and list it */
restore_file(indexfilename,0,0,TRUE);
/* now position to the backup set */
rewind_tape(FALSE);
space_filemarks((element_number * 2) + 1);
current_tape_block_number = 0;
/* now process the restore */
total_bytes_read = 0;
filescompressed = 0;
filesuncompressed = 0;
process_restore(indexfilename,search_string);
/* now finish up */
DeleteFile(indexfilename);
rewind_tape(TRUE);
close_tape();
if ((filescompressed+filesuncompressed) <= 0)
{
printf("Warning no files in saveset %s found with search string %s \n",saveset,
search_string);
fflush(stdout);
}
else print_restore_stats();
}
/* ------------------------------------------------------------------------------------ */
void do_backup(saveset_name,search_string,do_subdirs)
char saveset_name[];
char search_string[];
BOOLEAN do_subdirs;
{
int free_element = 0;
int taken_element = 0;
DWORD dwThreadId;
read_tape_index();
rewind_tape(FALSE);
free_element = find_free_saveset_element();
if (free_element < 0)
report_error("No room for any more savesets on tape, initialize it or switch tapes \n",0,severe);
taken_element = find_saveset_element(saveset_name);
if (taken_element >= 0)
{
printf("Error: Saveset %s Already exists on the tape... Try another name. \n",saveset_name);
fflush(stdout);
report_error(" ",0,severe);
}
else
{
store_start_time();
/* now space to the correct file mark and start writing the backup */
space_filemarks((free_element * 2) + 1 ); // 1 extra to get over header */
/* reset the current tape block number to be relative from the beginning of the
save set */
current_tape_block_number = 0;
/* this should put the tape ready to write the backup since there is two file marks
per backup 1 before the backup and 1 between the backup and its directory so the
directory can be retrieved quickly ie element 0 is filemark 0 element4 is file mark
8 */
/* now do the backup */
total_original_size = 0;
total_backup_size = 0;
filescompressed = 0;
filesuncompressed = 0;
processed_all_files = FALSE;
/* initialize critical sections */
InitializeCriticalSection(&Protected_Element);
InitializeCriticalSection(&Protected_Queue);
/* set globals here */
global_process_subdirs = do_subdirs;
strcpy(Global_SearchString,search_string);
/* spawn a thread to process process_write_directory and go on here
to call mt_backup_files */
hThread = CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)mt_process_write_directory,
(LPVOID)filesuncompressed,0,&dwThreadId);
if (hThread == NULL)
{
printf("ERROR: child thread for compression failed to start \n");
printf(" error code = %d \n",GetLastError());
report_error(" ",0,severe);
}
else
{
/* now that the thread started call the receive routine to get process
the compressed files */
thread_active = TRUE;
/* allow this thread to sleep to give the compress thread time to do some
processing */
/* only sleep if doing compression */
if (want_compression)
Sleep(10000); /* ten seconds */
mt_backup_files();
}
/* close the thread handle */
CloseHandle(hThread);
thread_active = FALSE;
/* dont write marks if nothing was backed up */
if ((filescompressed + filesuncompressed) == 0)
{
printf("Warning no files found in search parameter %s \n",search_string);
fflush(stdout);
}
else
{
/* now write the file mark */
write_filemarks(1);
/* now write the directory file */
write_directory_file();
/* now write another file mark */
write_filemarks(1);
/* now fill in the total size/compressed size and rewind and rewrite header */
/* also print out status messages */
fill_in_header_element(saveset_name,total_original_size,total_backup_size,
todays_date,free_element);
/* now rewrite header */
write_tape_index(TRUE);
}
/* now rewind tape */
rewind_tape(TRUE);
close_tape();
print_backup_stats();
} /* is room for new saveset */
}
/* ------------------------------------------------------------------------------------ */
void disp_help()
{
printf(" USAGE for LKBACKUP Version 1.0 by L. Kahn 1993 \n");
printf("LKBACKUP [-d -q -c -s] -b saveset_name search_string [include_subdirs] \n");
printf("LKBACKUP [-d -q -c] -e [long_or_short] or LGKBACKUP -h or \n");
printf("LKBACKUP [-d -q -c -s] -i or\n");
printf("LKBACKUP [-d -q -c -s] -L saveset_name or\n");
printf("LKBACKUP [-d -q -c -s] -l or \n");
printf("LKBACKUP [-d -q -c -s] -r saveset_name search_string \n");
printf("LKBACKUP [-d -q -c -s] -C no_of_good_savesets\n");
printf("-b = Backup using the search string starting from the current directory, \n");
printf(" including subdirs is optional and depedent on the value of \n");
printf(" include_subddirs (t or f) \n");
printf("-e = Erase tape where erasing long or short is optional. Default is short \n");
printf("-h = Display this HELP message \n");
printf("-i = Initialize tape (necessary before usage) \n");
printf("-l = List tape (i.e., name of all savesets)\n");
printf("-L = List the contents of a specific saveset \n");
printf("-r = Restore the saveset_name using the search_string\n");
printf("-C = Catalog tape (set index to say there are no_good_savesets) \n");
printf(" Should be used if for some reason a backup fails or power goes out\n");
printf(" during a backup. Rewrites the tape index, restores can then be \n");
printf(" performed but further backups may be unreliable.\n");
printf("-d = debug main, -q = quiet_mode, -D debug thread, -B debug both,\n");
printf("-c = turn comprssion on, -s use setmarks not filemarks");
}
/* ------------------------- main program */
void main(int argc,char *argv[])
{
int current_arg = 1;
BOOLEAN more_args = TRUE;
BOOLEAN done = FALSE;
BOOLEAN do_subdirs = FALSE;
file_mapping = FALSE;
want_compression = FALSE; /* this also does not speed things up and uses more tape
since the drive cannot keep streaming */
fill_in_todays_date();
if ((argc < 2) || (argc > 8))
disp_help();
else
{
/* process arguments */
if (argv[current_arg][0] != '-')
disp_help();
else
do
{
/* get the first one and if it doesn't start with a - we have a problem */
switch (argv[current_arg][1])
{
case 'q':
quiet_mode = TRUE;
break;
case 'c':
want_compression = TRUE;
break;
/* undocumented default is no file mapping since this does not seem to speed
things up */
case 'm':
file_mapping = TRUE;
break;
case 'd':
debug = TRUE;
break;
case 'D':
debug_child = TRUE;
break;
case 'B':
debug_child = TRUE;
debug = TRUE;
break;
case 'h':
disp_help();
done = TRUE;
break;
case 's':
set_mark_positioning = TRUE;
break;
case 'C':
if (argc < (current_arg + 2))
{
printf("ERROR: Number of good savesets needed for catalog procedure \n");
fflush(stdout);
}
else {
catalog_tape(argv[current_arg + 1]);
}
done = TRUE;
break;
case 'i':
initialize_tape();
done = TRUE;
break;
case 'l':
list_tape();
done = TRUE;
break;
case 'L':
if (argc < (current_arg + 2))
{
printf("ERROR: Saveset name needed for tape listing. Use LKBACKUP -h for help \n");
fflush(stdout);
}
else {
list_saveset(argv[current_arg + 1]);
}
done = TRUE;
break;
case 'e':
if (argc >= (current_arg + 2))
{
/* we have a short or long option so check it */
switch (argv[current_arg+1][0])
{
case 's':
erase_tape(FALSE);
done = TRUE;
break;
case 'l':
erase_tape(TRUE);
done = TRUE;
break;
default:
printf("ERROR: Legal options for erase are s for short erase or l for long erase \n");
printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
if (done)
break;
} /* end have extra arg */
else erase_tape(FALSE);
done = TRUE;
break;
case 'b':
/* make sure we have enough parms */
if (argc < (current_arg+3))
{
printf("ERROR: The search_string and the saveset_name are required for a backup operation. \n");
printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
/* check for include subdirs */
if (argc == (current_arg + 4))
{
switch (argv[current_arg+3][0])
{
case 't':
do_subdirs = TRUE;
break;
case 'f':
do_subdirs = FALSE;
break;
default:
printf("Error: The legal options for including subdirectories are t for f.\n");
printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
} /* have optional parm */
if (done)
break;
/* if we get here do the backup */
if (debug)
{
printf("calling backup %s %s %d \n",argv[current_arg+1],
argv[current_arg+2],do_subdirs);
fflush(stdout);
}
do_backup(argv[current_arg+1],argv[current_arg+2],do_subdirs);
done = TRUE;
break;
case 'r':
/* make sure we have enough parms */
if (argc < (current_arg+3))
{
printf("ERROR: The search_string and the saveset_name are required for a restore operation. \n"); printf("Use LKBACKUP -h for help \n");
fflush(stdout);
done = TRUE;
break;
}
else
{
if (debug)
{
printf("Restore %s %s \n",argv[current_arg+1],argv[current_arg+2]);
fflush(stdout);
}
do_restore(argv[current_arg+1],argv[current_arg+2]);
done = TRUE;
break;
}
default:
printf("Illegal option %s \n",argv[current_arg]);
disp_help();
done = TRUE;
break;
} /* end of switch */
++current_arg;
if (current_arg > argc)
more_args = FALSE;
} while ((!done) && (more_args));
} /* end of ok case */
} /* end of main */